from flask import Blueprint
from flask import request
from flask import render_template
from flask import flash
from flask import redirect
from flask import url_for

from app import db

from werkzeug import generate_password_hash

from app.wtforms.usuario_forms import UsuarioBuscar
from app.wtforms.usuario_forms import UsuarioEditable
from app.wtforms.usuario_forms import UsuarioNoEditable
from app.wtforms.usuario_forms import UsuarioModificacion
from app.wtforms.usuario_forms import UsuarioClave

from app.models.rol import Rol
from app.models.usuario import Usuario

from app.security import permission


mod = Blueprint('usuarios', __name__, url_prefix='/usuario')


@mod.route('/administracion/', methods=['GET', 'POST'])
@permission('ADMINISTRACION_USUARIOS')
def administracion_usuario():
    """
    Muestra en pantalla los usuarios que existen en la base de datos.
    Si no recibe algun filtro como parametro, lista todos los usuarios.
    Si recibe algun filtro, muestra los usuarios que cumplen con el filtro indicado
    """   
   
    form =  UsuarioBuscar(request.form)
   
    nombreFilter = form.nombre.data
    mailFilter = form.email.data
    estadoFilter = form.estado.data
    
    if(nombreFilter == None):
        nombreFilter = ''
    if(mailFilter == None):
        mailFilter = ''
    if(estadoFilter == None):
        estadoFilter = ''
  
    usuarios = Usuario.query.filter(Usuario.nombre.like( '%'+nombreFilter+'%' ) , Usuario.email.like( '%'+mailFilter+'%' ), Usuario.estado.like('%'+estadoFilter+'%'))
   
     
    return render_template('usuarios/administracion_usuario.html', form = form, usuarios = usuarios)


@mod.route('/crear/', methods=['GET', 'POST'])
@permission('CREAR_USUARIO')
def crear_usuario():
    """
    Muestra en pantalla el formulario de creacion de usuario, valida los datos ingresados por
    el usuario, hace las validaciones de que el nombre del usuario nuevo no exista ya en el
    sistema y se hayan ingresado los datos obligatorios. Luego almacena en base de datos
    """
    
    # Obtenemos el formulario
    form = UsuarioEditable(request.form)
        
    # Obtenemos todos los roles existentes en la base de datos
    roles = Rol.query.all()
    
    # Hacemos una tupla con el nombre y id de los roles
    lista_roles=[]
    for rol in roles:
        lista_roles.append((rol.id, rol.nombre))
    
    # Asignamos esa tupla de roles a la lista que va a ser visualizada en el checkbox  
    form.roles.choices = lista_roles
    
    # Se valida los datos ingresados en el formulario
    if form.validate_on_submit():
        
        # Obtenemos todos los usuarios de la base de datos
        usuarios = Usuario.query.all()
        cont = 0
        
        # Comparamos que el nombre ingresado por el usuario no sea igual a uno existente
        if usuarios != None:
            for usu in usuarios:
                if form.nombre.data == usu.nombre:
                    cont = cont + 1
         
        # Si ya existe el nombre, no permitimos la creacion           
        if cont != 0:
            flash("El nombre de usuario ya existe, elija otro")
            return redirect(url_for('usuarios.crear_usuario'))
           
        # Si el nombre aun no existe
        else:
            
            # Obtenemos los roles seleccionados por el usuario
            lista_roles = []
            for id_rol in form.roles.data:    
                rol = Rol.query.filter_by(id=id_rol).first()
                lista_roles.append(rol)
            
            # Creamos el usuario
            usuario = Usuario(form.nombre.data, form.email.data,  generate_password_hash(form.contrasenha.data),
                              form.pregunta.data, form.respuesta.data, 'ACTIVO', lista_roles)
            db.session.add(usuario)
            db.session.commit()
        
        # Una vez creado el nuevo usuario, se redirecciona a la pagina de administracion
        flash('El usuario ha sido registrado con exito')     
        return redirect(url_for('usuarios.administracion_usuario'))
          
    return render_template('usuarios/crear_usuario.html', form = form)


@mod.route('/modificar/<usuario>/', methods=['GET', 'POST'])
@permission('MODIFICAR_USUARIO')
def modificar_usuario(usuario):
    """
    Clase para modificar los atributos de un usuario existente en el sistema, muestra en pantalla todos
    los datos del usuario almacenado en base de datos para su modificacion
    @param usuario: id del usuario cuyos datos se quiere modificar
    """
    
    # Obtenemos el formulario
    form = UsuarioModificacion(request.form)
    
    # Obtenemos el usuario seleccionado
    usuario_seleccionado = Usuario.query.filter_by(id=usuario).first()
    
    # Obtenemos todos los roles existentes en la base de datos
    roles = Rol.query.all()
    
    # Hacemos una tupla con el nombre y id de los roles
    lista_roles=[]
    for rol in roles:
        lista_roles.append((rol.id, rol.nombre))
    
    # Asignamos esa tupla de roles a la lista que va a ser visualizada en el checkbox  
    form.roles.choices = lista_roles
    
    # Se valida los datos ingresados en el formulario
    if form.validate_on_submit():
        
        # Obtenemos todos los usuarios de la base de datos
        usuarios = Usuario.query.all()
        cont = 0
        
        # Comparamos que el nombre ingresado por el usuario no sea igual a uno existente
        if usuarios != None:
            for usu in usuarios:
                if form.nombre.data == usu.nombre:
                    cont = cont + 1
         
        # Si ya existe el nombre, no permitimos la creacion           
        if cont != 0 and form.nombre.data != usuario_seleccionado.nombre:
            flash("El nombre de usuario ya existe, elija otro")
            return redirect(url_for('usuarios.crear_usuario'))
           
        # Si el nombre aun no existe
        else:
            
            # Obtenemos los roles seleccionados por el usuario
            lista_roles = []
            for id_rol in form.roles.data:    
                rol = Rol.query.filter_by(id=id_rol).first()
                lista_roles.append(rol)
            
            # Guardamos los cambios del usuario
            usuario_seleccionado.setNombre(form.nombre.data)
            usuario_seleccionado.setEmail(form.email.data)
            usuario_seleccionado.setPregunta(form.pregunta.data)
            usuario_seleccionado.setRespuesta(form.respuesta.data)
            usuario_seleccionado.setRoles(lista_roles)
            db.session.add(usuario_seleccionado)
            db.session.commit()
        
        # Una vez creado el nuevo usuario, se redirecciona a la pagina de administracion
        flash('El usuario ha sido registrado con exito')     
        return redirect(url_for('usuarios.administracion_usuario'))
    
    # Mostramos en el formulario la descripcion y el nombre actual del rol que se quiere
    # modificar
    form.nombre.data = usuario_seleccionado.nombre
    form.email.data = usuario_seleccionado.email
    form.pregunta.data = usuario_seleccionado.pregunta
    form.respuesta.data = usuario_seleccionado.respuesta
            
    # Obtenemos los permisos que el rol seleccionado tiene antes de la modificacion
    roles_seleccionados = []
    for rol_sec in usuario_seleccionado.roles:
        roles_seleccionados.append(rol_sec.id)
      
    # Mostramos seleccionados esos permisos en el checkbox  
    form.roles.data = roles_seleccionados
    return render_template('usuarios/modificar_usuario.html', form = form, usuario=usuario)


@mod.route('/clave/<usuario>/', methods=['GET', 'POST'])
@permission('MODIFICAR_USUARIO')
def cambiar_clave(usuario):
    """
    Clase utilizada para la modificacion de clave de un usuario
    @param usuario: id del usuario cuya clave se quiere modificar
    """
    
    form = UsuarioClave(request.form)
    
    # Obtenemos el usuario seleccionado
    usuario_seleccionado = Usuario.query.filter_by(id=usuario).first()
    
    
    # Realizamos la validacion de los datos ingresados al formulario
    if request.method == 'POST' and form.is_submitted() and form.validate():
        
        usuario_seleccionado.setContrasenha(generate_password_hash(form.contrasenha.data))
            
        # Add y comiteamos los cambios hechos al usuario
        db.session.add(usuario_seleccionado)
        db.session.commit()
            
        # Redirigimos a pagina de modificacion de usuario
        return redirect(url_for('usuarios.modificar_usuario', usuario=usuario))
    
    return render_template('usuarios/ingreso_contrasenha_usuario.html', form = form,
                            usuario=usuario)


@mod.route('/consultar/<usuario>/', methods=['GET', 'POST'])
@permission('VER_USUARIO')
def consultar_usuario(usuario):
    """
    Muestra en pantalla el formulario de consulta de usuarios, muestra todos los datos del
    usuario seleccionado
    @param usuario: id del usuario que se desea consultar
    """
    
    # Obtenemos el formulario
    form = UsuarioNoEditable(request.form)
    
    # Obtenemos el usuario seleccionado
    usuario_seleccionado = Usuario.query.filter_by(id=usuario).first()
    
    # Hacemos una tupla con el nombre y el id de los roles del usuario
    roles_seleccionados = []
    for rol in usuario_seleccionado.roles:
        roles_seleccionados.append((rol.id, rol.nombre))
    
    # Mostramos los roles que posee el usuario   
    form.roles.choices = roles_seleccionados
    # Mostramos el nombre del usuario
    form.nombre.data = usuario_seleccionado.nombre
    #Mostramos el mail del usuario
    form.email.data = usuario_seleccionado.email
    # Mostramos el estado del usuario
    form.estado.data = usuario_seleccionado.estado

    if form.validate_on_submit():
        
        #Cuando el usuario presiona aceptar, redirigimos a la pagina de administracion de usuarios
        return redirect(url_for('usuarios.administracion_usuario'))
    
    return render_template('usuarios/consultar_usuario.html', form = form, 
                           usuario_seleccionado=usuario_seleccionado)
    

@mod.route('/desactivar/<usuario>/', methods=['GET', 'POST'])
@permission('DESACTIVAR_USUARIO')
def desactivar_usuario(usuario):
    """
    Realiza la desactivacion de usuarios con estado activo
    @param usuario: id del usuario que se desea desactivar
    """
    
    #Obtenemos el usuario seleccionado
    usuario_seleccionado = Usuario.query.filter_by(id=usuario).first()
    
    if usuario_seleccionado.estado == 'DESACTIVO':
        # Si el usuario seleccionado ya se encuentra con el estado desactivo
        # mostramos un mensaje indicando el hecho
        flash('El usuario ya se encuentra con el estado DESACTIVO', 
              'error-message')
        return redirect(url_for('usuarios.administracion_usuario'))
    
    else:
        # Si el usuario se encuentra con estado activo
        # Cambiamos el estado del usuario por desactivado
        usuario_seleccionado.setEstado('DESACTIVO')
        db.session.add(usuario_seleccionado)
        db.session.commit()
            
        # Redirigimos a la pagina de administracion de usuarios
        flash('El usuario ha sido desactivado con exito')
        return redirect(url_for('usuarios.administracion_usuario'))
        
        # Hacemos una tupla con el nombre y el id de los roles del usuario
        #roles_seleccionados = []
        #for rol in usuario_seleccionado.roles:
        #    roles_seleccionados.append((rol.id, rol.nombre))
    
        #Mostramos la lista de roles que posee el usuario    
        #form.roles.choices = roles_seleccionados
        # Mostramos el nombre del usuario
        #form.nombre.data = usuario_seleccionado.nombre
        # Mostramos el mail del usuario
        #form.email.data = usuario_seleccionado.email
        # Mostramos el estado del usuario
        #form.estado.data = usuario_seleccionado.estado
        #return render_template('usuarios/eliminar_usuario.html', form = form, 
        #                   usuario_seleccionado=usuario_seleccionado)
        

@mod.route('/activar/<usuario>/', methods=['GET', 'POST'])
@permission('ACTIVAR_USUARIO')
def activar_usuario(usuario):
    """
    Realiza la activacion de usuarios con estado desactivo
    @param usuario: id del usuario que se desea activar
    """
    
    #Obtenemos el usuario seleccionado
    usuario_seleccionado = Usuario.query.filter_by(id=usuario).first()
    
    if usuario_seleccionado.estado == 'ACTIVO':
         # Si el usuario seleccionado ya se encuentra con el estado desactivo
        # mostramos un mensaje indicando el hecho
        flash('El usuario ya se encuentra con el estado ACTIVO', 
              'error-message')
        return redirect(url_for('usuarios.administracion_usuario'))
    
    else:
        # Si el usuario se encuentra con estado activo
        # Cambiamos el estado del usuario por desactivado
        usuario_seleccionado.setEstado('ACTIVO')
        db.session.add(usuario_seleccionado)
        db.session.commit()
            
        # Redirigimos a la pagina de administracion de usuarios
        flash('El usuario ha sido activado con exito')
        return redirect(url_for('usuarios.administracion_usuario'))
 
    
